package com.yonyou.pmclouds.workflow.service;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.NullNode;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.businessobject.util.SortListUtil;
import com.yonyou.pmclouds.workflow.entity.ApprovalRecordVO;
import com.yonyou.pmclouds.workflow.entity.ProcessRunTimeVO;
import com.yonyou.pmclouds.workflow.util.ApprovalStatusEnum;
import com.yonyou.pmclouds.workflow.util.DateCovertUtil;
import com.yonyou.pmclouds.workflow.util.ProcessServiceConst;
import com.yonyou.pmclouds.workflow.util.WorkFlowConst;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import yonyou.bpm.rest.HistoryService;
import yonyou.bpm.rest.TaskService;
import yonyou.bpm.rest.exception.RestException;
import yonyou.bpm.rest.request.historic.HistoricProcessInstancesQueryParam;
import yonyou.bpm.rest.request.historic.HistoricTaskQueryParam;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 审批记录服务类，用与从云审批获取历史审批记录
 *
 * @author zhangzhonghao
 */

@Service
public class ProcessApprovalRecordService {

    public List<ProcessRunTimeVO> getApprovalRecord(String userId, String tenantId, String businessKey) throws BusinessException {
        JsonNode jsonNode;
        try {
            HistoryService historyService = getDefaultHistoryService(userId, tenantId);

            // 根据业务主键获取历史任务列表
            HistoricTaskQueryParam queryParam = new HistoricTaskQueryParam();
            queryParam.setTenantIdLike(tenantId);
            queryParam.setProcessBusinessKey(businessKey);
            jsonNode = (JsonNode) historyService.getHistoricTaskInstances(queryParam);
            if (jsonNode == null) {
                throw new BusinessException(WorkFlowConst.YS_NULL_RESP_MSG);
            }
            // 将历史任务转化为审批记录VO
            List<ProcessRunTimeVO> runTimeVOList = this.getApprovalInfoByNode(jsonNode, userId, tenantId);

            if (runTimeVOList != null && runTimeVOList.size() > 0) {
                String processInstanceId = runTimeVOList.get(0).getProcessInstanceId();
                ProcessRunTimeVO runTimeVO = this.getCreateInfo(processInstanceId, userId, tenantId);
                runTimeVOList.add(runTimeVO);

                SortListUtil.sort(runTimeVOList, new String[]{"seq", "startTime"}, new String[]{"asc", "asc"});

                // 审批轨迹顺序按审批时间正序排列
                for (ProcessRunTimeVO processRunTimeVO : runTimeVOList) {
                    List<ApprovalRecordVO> recordVOList = processRunTimeVO.getApprovalRecordVOList();
                    if (recordVOList != null && recordVOList.size() > 1) {
                        SortListUtil.sort(recordVOList, "endTime", "asc");
                    }
                }

            }

            return runTimeVOList;
        } catch (RestException e) {
            throw new BusinessException("获取历史审批记录异常 ：" + e.getMessage());
        }
    }

    /**
     * 获取根据环节点分类好的审批信息
     *
     * @param jsonNode 历史任务
     * @return 审批记录
     */
    private List<ProcessRunTimeVO> getApprovalInfoByNode(JsonNode jsonNode, String userId, String tenantId)
            throws BusinessException, RestException {
        List<ProcessRunTimeVO> runTimeVOList = new ArrayList<>();
        // 获取分类好的审批记录
        Map<String, List<ApprovalRecordVO>> activityMap = this.getApprovalNodeInfo(jsonNode, userId, tenantId);

        if (activityMap == null) {
            return null;
        }

        for (Map.Entry<String, List<ApprovalRecordVO>> entry : activityMap.entrySet()) {
            ProcessRunTimeVO runTimeVO = new ProcessRunTimeVO();
            // 先都默认为1，提交人为0
            runTimeVO.setSeq(1);
            List<ApprovalRecordVO> recordVOList = entry.getValue();
            if (recordVOList != null) {
                StringBuilder recordStatusBuilder = new StringBuilder();
                for (ApprovalRecordVO recordVO : recordVOList) {
                    runTimeVO.setApprovalNodeName(recordVO.getApprovalNodeName());
                    runTimeVO.setApprovalNodeId(recordVO.getApprovalNodeKey());
                    runTimeVO.setStartTime(recordVO.getStartTime());
                    runTimeVO.setProcessInstanceId(recordVO.getProcessInstanceId());
                    recordStatusBuilder.append(recordVO.getApprovalStatus());
                }

                if(recordStatusBuilder.toString().contains(ApprovalRecordVO.APPROVAL_STATUS_APPROVAL_PENDING)){
                    // 判断是否为待审状态
                    runTimeVO.setApprovalStatus(ApprovalRecordVO.APPROVAL_STATUS_APPROVAL_PENDING);
                    runTimeVO.setApprovalStatusDesc(ApprovalStatusEnum.getName(ApprovalRecordVO.APPROVAL_STATUS_APPROVAL_PENDING));
                }else if(recordStatusBuilder.toString().contains(ApprovalRecordVO.APPROVAL_STATUS_REJECT)){
                    // 判断是否为驳回状态
                    runTimeVO.setApprovalStatus(ApprovalRecordVO.APPROVAL_STATUS_REJECT);
                    runTimeVO.setApprovalStatusDesc(ApprovalStatusEnum.getName(ApprovalRecordVO.APPROVAL_STATUS_REJECT));
                }else if (StringUtils.isEmpty(recordStatusBuilder.toString().replaceAll(ApprovalRecordVO.APPROVAL_STATUS_DELETED, ""))) {
                    // 判断是否全部为删除状态，如果是则过滤掉该信息
                    runTimeVO.setApprovalStatus(ApprovalRecordVO.APPROVAL_STATUS_DELETED);
                    runTimeVO.setApprovalStatusDesc(ApprovalStatusEnum.getName(ApprovalRecordVO.APPROVAL_STATUS_DELETED));
                }else if (StringUtils.isEmpty(recordStatusBuilder.toString().replaceAll(ApprovalRecordVO.APPROVAL_STATUS_DELETED, "")
                        .replaceAll(ApprovalRecordVO.APPROVAL_STATUS_ADOPT, ""))) {
                    // 判断是否全部审批通过，如果该环节点中所有任务全部审批通过，则该节点状态置为审批通过
                    runTimeVO.setApprovalStatus(ApprovalRecordVO.APPROVAL_STATUS_ADOPT);
                    runTimeVO.setApprovalStatusDesc(ApprovalStatusEnum.getName(ApprovalRecordVO.APPROVAL_STATUS_ADOPT));
                }

                runTimeVO.setApprovalRecordVOList(recordVOList);
            }
            runTimeVOList.add(runTimeVO);
        }

        // 过滤掉被抢占审批的人
        return this.filterDeletedPerson(runTimeVOList);
    }

    /**
     * 将历史任务根据环节点进行分类组合
     *
     * @param jsonNode 历史任务
     * @return 审批记录
     */
    private Map<String, List<ApprovalRecordVO>> getApprovalNodeInfo(JsonNode jsonNode, String userId, String tenantId)
            throws BusinessException, RestException {
        Map<String, List<ApprovalRecordVO>> recordMap = new HashMap<>();

        JsonNode dataNode = jsonNode.findValue(ProcessServiceConst.FIELD_DATA);
        if (dataNode instanceof NullNode) {
            return null;
        }
        ArrayNode arrayNode = (ArrayNode) jsonNode.findValue(ProcessServiceConst.FIELD_DATA);

        if (arrayNode != null && arrayNode.size() > 0) {

            List<ApprovalRecordVO> recordVOList = new ArrayList<>();
            for (JsonNode taskNode : arrayNode) {

                // 过滤掉抢占或会签中未审批的人，因为UI界面上面需要显示所有审批人，注释掉过滤条件
//                if ("deleted".equalsIgnoreCase(taskNode.findValue("deleteReason").textValue()) &&
//                        taskNode.findValue("finished").booleanValue()) {
//                    continue;
//                }

                // 将任务转为审批记录VO
                ApprovalRecordVO recordVO = this.covertNodeToApprovalVO(taskNode, userId, tenantId);

                recordVOList.add(recordVO);

            }

            // 将审批任务按开始时间升序排列
            SortListUtil.sort(recordVOList, "startTime", "asc");

            // 循环遍历时如果环节点ID和驳回到某一环节的ID相同时，则认为驳回重新审批的环节，重新为一组
            String rejectActivityId = "";
            Map<String, List<ApprovalRecordVO>> activityMap = new HashMap<>();
            List<Map<String, List<ApprovalRecordVO>>> recordSortList = new ArrayList<>();
            for (ApprovalRecordVO recordVO : recordVOList) {

                if (recordVO.getApprovalNodeKey().equalsIgnoreCase(rejectActivityId)) {
                    recordSortList.add(activityMap);
                    activityMap = new HashMap<>();
                    rejectActivityId = "";
                }

                if (StringUtils.isNotEmpty(recordVO.getRejectActivityId())) {
                    rejectActivityId = recordVO.getRejectActivityId();
                }

                List<ApprovalRecordVO> recordVOS = activityMap.get(recordVO.getApprovalNodeKey());

                if (recordVOS == null) {
                    recordVOS = new ArrayList<>();
                    recordVOS.add(recordVO);
                    activityMap.put(recordVO.getApprovalNodeKey(), recordVOS);
                } else {
                    recordVOS.add(recordVO);
                }

            }

            recordSortList.add(activityMap);

            for (int i = 0; i < recordSortList.size(); i++) {
                for (Map.Entry<String, List<ApprovalRecordVO>> entry : recordSortList.get(i).entrySet()) {
                    recordMap.put(entry.getKey() + "_" + String.valueOf(i), entry.getValue());
                }
            }


        }
        return recordMap;
    }

    /**
     * 将任务信息转化为审批记录数据
     *
     * @param jsonNode 历史任务信息
     * @return 审批记录
     */
    private ApprovalRecordVO covertNodeToApprovalVO(JsonNode jsonNode, String userId, String tenantId)
            throws BusinessException, RestException {
        String taskId = jsonNode.findValue(ProcessServiceConst.FIELD_ID).textValue();
        String taskDefinitionKey = jsonNode.findValue("taskDefinitionKey").textValue();
        String startTime = jsonNode.findValue("startTime").textValue();
        boolean finished = jsonNode.findValue("finished").booleanValue();
        String deleteReason = jsonNode.findValue("deleteReason").textValue();
        String processDefinitionId = jsonNode.findValue("processDefinitionId").textValue();
        String processInstanceId = jsonNode.findValue("processInstanceId").textValue();
        // 将任务信息存储到审批记录中
        ApprovalRecordVO recordVO = new ApprovalRecordVO();
        recordVO.setProcessDefinitionId(processDefinitionId);
        recordVO.setProcessInstanceId(processInstanceId);
        recordVO.setApprovalPersonCode(jsonNode.findValue("assignee").textValue());
        recordVO.setStartTime(DateCovertUtil.covertUTCToDateStr(startTime));
        recordVO.setEndTime(DateCovertUtil.covertUTCToDateStr(jsonNode.findValue("endTime").textValue()));
        recordVO.setApprovalNodeName(jsonNode.findValue("name").textValue());
        recordVO.setApprovalNodeKey(taskDefinitionKey);
        recordVO.setTaskId(taskId);
        recordVO.setDeleteReason(deleteReason);
        recordVO.setTenantId(jsonNode.findValue("tenantId").textValue());
        recordVO.setFinished(finished);

        // 获取审批评论
        TaskService taskService = (TaskService) ProcessServiceFactory.getProcessService(ProcessServiceFactory.TASK_SERVICE, userId, tenantId);
        JsonNode commentsNode = (JsonNode) taskService.getComments(taskId);
        if (commentsNode != null && commentsNode.size() > 0) {
            recordVO.setApprovalComment(commentsNode.get(0).findValue("message").textValue());
        }

        // 审批状态赋值
        if ("completed".equalsIgnoreCase(deleteReason) && finished) {
            // 审批通过
            recordVO.setApprovalStatusDesc(ApprovalStatusEnum.getName(ApprovalRecordVO.APPROVAL_STATUS_ADOPT));
            recordVO.setApprovalStatus(ApprovalRecordVO.APPROVAL_STATUS_ADOPT);
        } else if (("deleted".equalsIgnoreCase(deleteReason) || "delete".equalsIgnoreCase(deleteReason)) && finished) {
            // 抢占或者会签中未审批中的人
            recordVO.setApprovalStatusDesc(ApprovalStatusEnum.getName(ApprovalRecordVO.APPROVAL_STATUS_DELETED));
            recordVO.setApprovalStatus(ApprovalRecordVO.APPROVAL_STATUS_DELETED);
        } else if (deleteReason != null && finished) {
            // 驳回
            recordVO.setApprovalStatusDesc(ApprovalStatusEnum.getName(ApprovalRecordVO.APPROVAL_STATUS_REJECT));
            recordVO.setApprovalStatus(ApprovalRecordVO.APPROVAL_STATUS_REJECT);
            // 驳回原因不是用的评论，单独处理一下
            if (!deleteReason.contains("reject:{")) {
                recordVO.setApprovalComment(deleteReason);
            } else {
                deleteReason = deleteReason.substring(deleteReason.indexOf("{"));
                recordVO.setRejectActivityId(JSON.parseObject(deleteReason).getString("activityId"));
            }
        } else if (deleteReason == null && !finished) {
            // 待审批
            recordVO.setApprovalStatusDesc(ApprovalStatusEnum.getName(ApprovalRecordVO.APPROVAL_STATUS_APPROVAL_PENDING));
            recordVO.setApprovalStatus(ApprovalRecordVO.APPROVAL_STATUS_APPROVAL_PENDING);
        }


        return recordVO;
    }

    /**
     * 从流程实例中获取制单人信息
     *
     * @param processInstanceId 流程实例ID
     * @return 开始节点数据
     */
    private ProcessRunTimeVO getCreateInfo(String processInstanceId, String userId, String tenantId)
            throws BusinessException, RestException {
        // 获取流程实例信息
        HistoricProcessInstancesQueryParam queryParam = new HistoricProcessInstancesQueryParam();
        queryParam.setProcessInstanceId(processInstanceId);
        HistoryService historyService = getDefaultHistoryService(userId, tenantId);
        JsonNode jsonNode = (JsonNode) historyService.getHistoricProcessInstances(queryParam);
        if (jsonNode == null) {
            throw new BusinessException(WorkFlowConst.YS_NULL_RESP_MSG);
        }
        ProcessRunTimeVO runTimeVO = new ProcessRunTimeVO();
        if (jsonNode.findValue(ProcessServiceConst.FIELD_DATA) != null &&
                jsonNode.findValue(ProcessServiceConst.FIELD_DATA).size() > 0) {
            ApprovalRecordVO recordVO = new ApprovalRecordVO();
            JsonNode instanceNode = jsonNode.findValue(ProcessServiceConst.FIELD_DATA).get(0);
            recordVO.setApprovalComment("提交了单据");
            recordVO.setApprovalNodeName("制单人");
            recordVO.setApprovalStatus(ApprovalRecordVO.APPROVAL_STATUS_SUBMIT);
            recordVO.setApprovalStatusDesc(ApprovalStatusEnum.getName(ApprovalRecordVO.APPROVAL_STATUS_SUBMIT));
            recordVO.setFinished(true);
            // 将流程启动时间设置为制单日期
            recordVO.setStartTime(DateCovertUtil.covertUTCToDateStr(instanceNode.findValue("startTime").textValue()));
            recordVO.setEndTime(DateCovertUtil.covertUTCToDateStr(instanceNode.findValue("startTime").textValue()));
            recordVO.setApprovalPersonCode(instanceNode.findValue("startUserId").textValue());
            recordVO.setProcessInstanceId(processInstanceId);
            recordVO.setProcessDefinitionId(instanceNode.findValue("processDefinitionId").textValue());
            recordVO.setBusinessKey(instanceNode.findValue("businessKey").textValue());
            recordVO.setApprovalNodeKey(instanceNode.findValue("startActivityId").textValue());
            recordVO.setTenantId(instanceNode.findValue("tenantId").textValue());

            runTimeVO.setApprovalStatus(recordVO.getApprovalStatus());
            runTimeVO.setApprovalStatusDesc(recordVO.getApprovalStatusDesc());
            runTimeVO.setProcessInstanceId(processInstanceId);
            runTimeVO.setApprovalNodeId(recordVO.getApprovalNodeKey());
            runTimeVO.setApprovalNodeName(recordVO.getApprovalNodeName());
            runTimeVO.setAllApprovalPersonCode(recordVO.getApprovalPersonCode());
            // 根据开始时间字段排序，制单人排列在最上面
            runTimeVO.setStartTime(recordVO.getStartTime());
            List<ApprovalRecordVO> recordVOList = new ArrayList<>();
            recordVOList.add(recordVO);
            runTimeVO.setApprovalRecordVOList(recordVOList);
            runTimeVO.setSeq(0);
        }
        return runTimeVO;

    }

    /**
     * 将未审批被抢占的人过滤掉
     *
     * @param runTimeVOList 审批记录
     */
    private List<ProcessRunTimeVO> filterDeletedPerson(List<ProcessRunTimeVO> runTimeVOList) {
        List<ProcessRunTimeVO> newRunTimeList = new ArrayList<>();
        for (ProcessRunTimeVO runTimeVO : runTimeVOList) {
            if(ApprovalRecordVO.APPROVAL_STATUS_DELETED.equalsIgnoreCase(runTimeVO.getApprovalStatus())){
                continue;
            }
            StringBuilder stringBuilder = new StringBuilder();
            List<ApprovalRecordVO> newApprovalRecordList = new ArrayList<>();
            for (ApprovalRecordVO recordVO : runTimeVO.getApprovalRecordVOList()) {
                stringBuilder.append(",").append(recordVO.getApprovalPersonCode());
                if (!ApprovalRecordVO.APPROVAL_STATUS_DELETED.equalsIgnoreCase(recordVO.getApprovalStatus())) {
                    newApprovalRecordList.add(recordVO);
                }
            }
            runTimeVO.setAllApprovalPersonCode(stringBuilder.substring(1));
            runTimeVO.setApprovalRecordVOList(newApprovalRecordList);
            newRunTimeList.add(runTimeVO);
        }
        return newRunTimeList;
    }

    /**
     * 获取第一个环节点ID
     *
     * @param userId      操作人ID
     * @param tenantId    租户ID
     * @param businessKey 单据主键
     */
    public String getFirstNodeId(String userId, String tenantId, String businessKey) throws BusinessException {
        String activityId = "";
        List<ProcessRunTimeVO> recordList = this.getApprovalRecord(userId, tenantId, businessKey);
        if (recordList != null && recordList.size() > 1) {
            // 第一个为制单人节点，取第二个
            activityId = recordList.get(1).getApprovalNodeId();
        }
        return activityId;
    }

    private HistoryService getDefaultHistoryService(String userId, String tenantId) throws BusinessException {
        return (HistoryService) ProcessServiceFactory.getProcessService(ProcessServiceFactory.HISTORY_SERVICE, userId, tenantId);
    }

}
